package com.sqlcheck.config;

import com.sqlcheck.service.AuthService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;

/**
 * 认证拦截器
 * 统一处理用户认证和X-User-ID请求头注入
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AuthInterceptor implements HandlerInterceptor {

    private final AuthService authService;

    // 需要排除认证的路径
    private static final List<String> EXCLUDED_PATHS = Arrays.asList(
        "/auth/login",
        "/auth/validate",
        "/v3/api-docs",
        "/swagger-ui",
        "/swagger-resources",
        "/webjars",
        "/favicon.ico",
        "/error",
        "/scan-tasks"  // Allow access to scan tasks for testing
    );

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String requestPath = request.getRequestURI();
        String method = request.getMethod();

        log.debug("拦截请求: {} {}", method, requestPath);

        // 跳过OPTIONS请求（CORS预检）
        if ("OPTIONS".equals(method)) {
            return true;
        }

        // 检查是否需要排除认证
        if (isExcludedPath(requestPath)) {
            log.debug("跳过认证检查: {}", requestPath);
            return true;
        }

        // 获取Authorization头
        String authHeader = request.getHeader("Authorization");
        if (authHeader == null || authHeader.trim().isEmpty()) {
            log.warn("请求缺少Authorization头: {}", requestPath);
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"success\":false,\"message\":\"未授权访问，请先登录\"}");
            return false;
        }

        // 提取token
        String token = extractTokenFromHeader(authHeader);
        if (token == null) {
            log.warn("无效的Authorization头格式: {}", requestPath);
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"success\":false,\"message\":\"无效的认证头格式\"}");
            return false;
        }

        // 验证token并获取用户ID
        try {
            if (!authService.validateToken(token)) {
                log.warn("Token验证失败: {}", requestPath);
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().write("{\"success\":false,\"message\":\"访问令牌无效或已过期\"}");
                return false;
            }

            Long userId = authService.getUserIdFromToken(token);
            if (userId == null) {
                log.warn("无法从token中获取用户ID: {}", requestPath);
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().write("{\"success\":false,\"message\":\"无效的用户令牌\"}");
                return false;
            }

            // 注入X-User-ID请求头
            request.setAttribute("X-User-ID", userId);
            
            log.debug("认证成功，注入用户ID: userId={}, path={}", userId, requestPath);
            return true;

        } catch (Exception e) {
            log.error("认证过程异常: path={}", requestPath, e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"success\":false,\"message\":\"认证服务异常\"}");
            return false;
        }
    }

    /**
     * 检查路径是否需要排除认证
     */
    private boolean isExcludedPath(String requestPath) {
        return EXCLUDED_PATHS.stream().anyMatch(excludedPath -> 
            requestPath.startsWith(excludedPath) || requestPath.contains(excludedPath));
    }

    /**
     * 从Authorization header中提取token
     */
    private String extractTokenFromHeader(String authHeader) {
        if (authHeader == null || authHeader.trim().isEmpty()) {
            return null;
        }

        if (authHeader.startsWith("Bearer ")) {
            return authHeader.substring(7);
        }

        // 直接返回token（向后兼容）
        return authHeader;
    }
}